package cn.com.surker.thread;

import com.alibaba.fastjson.JSONObject;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池
 * @author luotao
 * @date 2023/4/3
 */
public class ThreadPools {


	//核心线程池,核心线程数量应该根据硬件性能进行配置,后面根据配置文件配置
	public static final int corePoolsize  = 12;

	//普通类型的线程池(默认最大线程数量以及对象数量)
	private static volatile ThreadPoolExecutor defualtCommonThreadPool;
	//普通类型的线程池(自定义最大线程数量以及对象数量)
	private static volatile ThreadPoolExecutor customCommonThreadPool1;
	//普通类型的线程池(自定义最大线程数量)
	private static volatile ThreadPoolExecutor customCommonThreadPool2;
	//不限数量的线程池
	private static volatile ThreadPoolExecutor limitlessThreadPool;
	//定时任务线程池
	private static volatile ScheduledThreadPoolExecutor scheduledThreadPool;


	/**
	 * 获取普通线程池;注意本线程池仅能用于会正常执行完毕的线程,不能用于while(true)类的线程
	 * 如果有while(true)等死循环的需求,请使用不限数量的线程池(不推荐),或定时任务线程池(推荐)
	 * 对于定时任务的需求,不建议使用while(true)来执行,因为使用while(true),该线程永远不会结束,如果任务太多,超过硬件限制,反而会更慢,且有可能引发内存泄漏问题
	 * 建议写成普通可执行完毕的线程,然后使用定时任务线程池
	 * @return
	 */
	public static ThreadPoolExecutor getCommonThreadPool(){
		if(null == defualtCommonThreadPool){
			synchronized (ThreadPools.class){
				if(null == defualtCommonThreadPool){
					defualtCommonThreadPool = new ThreadPoolExecutor(corePoolsize, 50, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50));
				}
			}
		}
		return defualtCommonThreadPool;
	}

	/**
	 * 获取普通线程池
	 * @param maximumPoolsize           最大线程数
	 * @param keepAliveTime             活跃时间
	 * @param unit                      活跃时间单位
	 * @param queueCount                队列长度
	 * @return
	 */
	public static ThreadPoolExecutor getCommonThreadPool(int maximumPoolsize, long keepAliveTime, TimeUnit unit, int queueCount){
		if(null == customCommonThreadPool1){
			synchronized (ThreadPools.class){
				if(null == customCommonThreadPool1){
					customCommonThreadPool1 = new ThreadPoolExecutor(corePoolsize, maximumPoolsize, keepAliveTime, unit, new LinkedBlockingQueue<>(queueCount));
				}
			}
		}
		return customCommonThreadPool1;
	}

	/**
	 * 获取普通线程池
	 * @param maximumPoolsize           最大线程数
	 * @return
	 */
	public static ThreadPoolExecutor getCommonThreadPool(int maximumPoolsize){
		if(null == customCommonThreadPool2){
			synchronized (ThreadPools.class){
				if(null == customCommonThreadPool2){
					customCommonThreadPool2 = new ThreadPoolExecutor(corePoolsize, maximumPoolsize, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50));
				}
			}
		}
		return customCommonThreadPool2;
	}

	/**
	 * 获取不限数量的线程池,此线程池适用于while(true)等不会正常退出的线程
	 * 注意,使用此线程池,如果线程太多,内存不够的话会出现内存溢出错误,不建议使用本线程池
	 * 如果有需要while(true)的,建议使用定时任务线程池(while(true)大多场景为定时任务)
	 * @return
	 */
	public static ThreadPoolExecutor getLimitlessThreadPool(){
		if(null == limitlessThreadPool){
			synchronized (ThreadPools.class){
				if(null == limitlessThreadPool){
					limitlessThreadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
				}
			}
		}
		limitlessThreadPool = new ScheduledThreadPoolExecutor(corePoolsize);
		return limitlessThreadPool;
	}

	/**
	 * 获取定时任务线程池
	 * 定时任务线程池三种提交方式,请根据实际情况进行操作
	 *  schedule：延迟多长时间之后只执行一次；
	 *  scheduledAtFixedRate：延迟指定时间后执行一次，之后按照固定的时长周期执行；
	 *  scheduledWithFixedDelay：延迟指定时间后执行一次，之后按照：上一次任务执行时长 + 周期的时长 的时间去周期执行；
	 * @return
	 */
	public static ScheduledThreadPoolExecutor getScheduledThreadPool(){
		if(null == scheduledThreadPool){
			synchronized (ThreadPools.class){
				if(null == scheduledThreadPool){
					scheduledThreadPool = new ScheduledThreadPoolExecutor(corePoolsize);
				}
			}
		}
		return scheduledThreadPool;
	}

	/**
	 * 查询全部的线程
	 *
	 * @return
	 */
	public static List<ThreadData> getAllThreads() {
		List<ThreadData> threadDataList = new ArrayList<>();
		Thread.getAllStackTraces().forEach((thread, stackTrace) -> {
			threadDataList.add(new ThreadData(
				thread.getId(),
				thread.getName(),
				thread.getState()
			));
		});
		threadDataList.sort(Comparator.comparing(ThreadData::getName)); // 核心排序
		return threadDataList;
	}

	public static void main(String[] args) {
		// 创建带自定义名称的线程池
		String qianzui = "MyScheduler";
		ScheduledThreadPoolExecutor scheduler = getScheduledThreadPool();
		scheduler.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Thread thread = Thread.currentThread();
				String name = thread.getName();
				thread.setName(qianzui + "_" + 1);
			}
		}, 0, 5, TimeUnit.SECONDS);
		scheduler.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Thread thread = Thread.currentThread();
				String name = thread.getName();
				thread.setName(qianzui + "_" + 2);
			}
		}, 10, 8, TimeUnit.SECONDS);

		scheduler.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Thread thread = Thread.currentThread();
				String name = thread.getName();
				thread.setName(qianzui + "_" + 3);
				List<ThreadData> allThreads = getAllThreads();
				String s = JSONObject.toJSONString(allThreads);
				System.err.println(s);
				;
			}
		}, 0, 10, TimeUnit.SECONDS);
	}
}

// 自定义线程工厂
class CustomThreadFactory implements ThreadFactory {
	private final AtomicInteger threadCount = new AtomicInteger(1);
	private final String namePrefix;

	public CustomThreadFactory(String poolName) {
		this.namePrefix = poolName + "-thread-";
	}

	@Override
	public Thread newThread(Runnable r) {
		Thread thread = new Thread(r);
		// 设置线程名称格式：poolName-thread-1, poolName-thread-2, ...
		thread.setName(namePrefix + threadCount.getAndIncrement());
		return thread;
	}
}